/**
 *
 */
package de.cbf.cam.dsa.facet.weapon_cc.editor;

import java.beans.IndexedPropertyChangeEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.swt.widgets.Control;

import de.cbf.cam.dsa.entity.edit.talent.resolver.service_resolver.IServiceResolver_EntityTalent;
import de.cbf.cam.dsa.facet.talent.FacetTalent;
import de.cbf.cam.dsa.facet.weapon_cc.FacetWeaponCC;
import de.cbf.cam.dsa.facet.weapon_cc.helper.WeaponCC_CombatValues;
import de.cbf.util.db.interfaces.exceptions.EntityLoadException;
import de.cbf.util.entity.edit.category_tree.dialogs.DialogChooseEntity;
import de.cbf.util.entity.edit.category_tree.helper.UUIDString;
import de.cbf.util.entity.facet.edit.composites.factorys.AbstractFacetSectionFactory;
import de.cbf.util.entity.facet.edit.controller.AbstractControllerEditFacet;
import de.cbf.util.entity.facet.entities.EntityCategorized;
import de.cbf.util.entity.facet.entities.EntityFacetReferences;
import de.cbf.util.ui.listener.IUiChangeListener;
import de.cbf.util.ui.listener.UiChangeEvent;
import de.cbf.util.uuidheader.entities.UUIDReference;

/**
 * @author Nebelritter
 *
 */
public class ControllerEditorFacetWeaponCC extends AbstractControllerEditFacet<FacetWeaponCC> {
	private static final Log logger = LogFactory.getLog(ControllerEditorFacetWeaponCC.class);

	public static final String TEXT_STATE_EVENT_Length_ERROR		= "Length setting not correct";
	public static final String TEXT_STATE_EVENT_Length_WARNING		= FacetWeaponCC.TEXT_UNSET_LENGTH;
	public static final String TEXT_STATE_EVENT_Bf_ERROR			= "Bf setting not correct";
	public static final String TEXT_STATE_EVENT_Bf_WARNING			= FacetWeaponCC.TEXT_UNSET_BF;
	public static final String TEXT_STATE_EVENT_Tp_ERROR			= "Tp setting not correct";
	public static final String TEXT_STATE_EVENT_Tp_WARNING			= WeaponCC_CombatValues.TEXT_UNSET_TP;
	public static final String TEXT_STATE_EVENT_TpKKBase_ERROR		= "TpKKBase setting not correct";
	public static final String TEXT_STATE_EVENT_TpKKBase_WARNING	= WeaponCC_CombatValues.TEXT_UNSET_TP_KK_BASE;
	public static final String TEXT_STATE_EVENT_TpKKStep_ERROR		= "TpKKStep setting not correct";
	public static final String TEXT_STATE_EVENT_TpKKStep_WARNING	= WeaponCC_CombatValues.TEXT_UNSET_TP_KK_STEP;
	public static final String TEXT_STATE_EVENT_Ini_ERROR			= "Ini setting not correct";
	public static final String TEXT_STATE_EVENT_Ini_WARNING			= WeaponCC_CombatValues.TEXT_UNSET_INI;
	public static final String TEXT_STATE_EVENT_WmAT_ERROR			= "WmAT setting not correct";
	public static final String TEXT_STATE_EVENT_WmAT_WARNING		= WeaponCC_CombatValues.TEXT_UNSET_WM_AT;
	public static final String TEXT_STATE_EVENT_WmPA_ERROR			= "WmPA setting not correct";
	public static final String TEXT_STATE_EVENT_WmPA_WARNING		= WeaponCC_CombatValues.TEXT_UNSET_WM_PA;
	public static final String TEXT_STATE_EVENT_DK_BITS_ERROR		= "WmPA setting not correct";	
	public static final String TEXT_STATE_EVENT_Talents_WARNING		= WeaponCC_CombatValues.TEXT_UNSET_TALENTS;
	
	protected static StateEvent STATE_EVENT_Length_ERROR 		= new StateEvent(TEXT_STATE_EVENT_Length_ERROR,		StateEvent.STATE_ERROR); 	
	protected static StateEvent STATE_EVENT_Length_WARNING		= new StateEvent(TEXT_STATE_EVENT_Length_WARNING,	StateEvent.STATE_WARNING); 
	protected static StateEvent STATE_EVENT_Bf_ERROR 			= new StateEvent(TEXT_STATE_EVENT_Bf_ERROR,			StateEvent.STATE_ERROR); 	
	protected static StateEvent STATE_EVENT_Bf_WARNING			= new StateEvent(TEXT_STATE_EVENT_Bf_WARNING,		StateEvent.STATE_WARNING); 
	protected static StateEvent STATE_EVENT_Tp_ERROR 			= new StateEvent(TEXT_STATE_EVENT_Tp_ERROR,			StateEvent.STATE_ERROR); 	
	protected static StateEvent STATE_EVENT_Tp_WARNING			= new StateEvent(TEXT_STATE_EVENT_Tp_WARNING,		StateEvent.STATE_WARNING); 
	protected static StateEvent STATE_EVENT_TpKKBase_ERROR 		= new StateEvent(TEXT_STATE_EVENT_TpKKBase_ERROR,	StateEvent.STATE_ERROR); 	
	protected static StateEvent STATE_EVENT_TpKKBase_WARNING	= new StateEvent(TEXT_STATE_EVENT_TpKKBase_WARNING,	StateEvent.STATE_WARNING); 
	protected static StateEvent STATE_EVENT_TpKKStep_ERROR 		= new StateEvent(TEXT_STATE_EVENT_TpKKStep_ERROR,	StateEvent.STATE_ERROR); 	
	protected static StateEvent STATE_EVENT_TpKKStep_WARNING	= new StateEvent(TEXT_STATE_EVENT_TpKKStep_WARNING,	StateEvent.STATE_WARNING); 
	protected static StateEvent STATE_EVENT_Ini_ERROR 			= new StateEvent(TEXT_STATE_EVENT_Ini_ERROR,		StateEvent.STATE_ERROR); 	
	protected static StateEvent STATE_EVENT_Ini_WARNING			= new StateEvent(TEXT_STATE_EVENT_Ini_WARNING,		StateEvent.STATE_WARNING); 
	protected static StateEvent STATE_EVENT_WmAT_ERROR 			= new StateEvent(TEXT_STATE_EVENT_WmAT_ERROR,		StateEvent.STATE_ERROR); 	
	protected static StateEvent STATE_EVENT_WmAT_WARNING		= new StateEvent(TEXT_STATE_EVENT_WmAT_WARNING,		StateEvent.STATE_WARNING); 
	protected static StateEvent STATE_EVENT_WmPA_ERROR 			= new StateEvent(TEXT_STATE_EVENT_WmPA_ERROR,		StateEvent.STATE_ERROR); 	
	protected static StateEvent STATE_EVENT_WmPA_WARNING		= new StateEvent(TEXT_STATE_EVENT_WmPA_WARNING,		StateEvent.STATE_WARNING); 
	protected static StateEvent STATE_EVENT_DK_BITS_ERROR 		= new StateEvent(TEXT_STATE_EVENT_DK_BITS_ERROR,	StateEvent.STATE_ERROR);
	protected static StateEvent STATE_EVENT_Talents_WARNING 	= new StateEvent(TEXT_STATE_EVENT_Talents_WARNING,	StateEvent.STATE_WARNING);
	
	protected static final UUIDReference INIT_TALENT = null;

	public static final String DIALOG_TITLE_CHOOSE_TALENT = "Choose Talent..";
	
	public static final String TEXT_SECTION_TALENTS = "Talents by Category"; 
	
	protected CompositeEditWeaponCC compositeEditWeaponCC;

	protected PCLFacetWeaponCC pclFacetWeaponCC;
	protected UILFacetWeaponCC uilFacetWeaponCC;

	protected NumberFormat formatInteger;	
	protected NumberFormat format;	

	protected UUIDReference activeTalent;

	//for talent tree
//	protected Class<? extends IFacetOfEntity> activeBaseFacet;
	protected IServiceResolver_EntityTalent serviceResolverTalents;
	/**
	 *
	 */
	public ControllerEditorFacetWeaponCC() {
	}

	@Override
	protected void init() {
		super.init();
		pclFacetWeaponCC = new PCLFacetWeaponCC();
		uilFacetWeaponCC = new UILFacetWeaponCC();

		formatInteger = NumberFormat.getIntegerInstance();
		formatInteger.setGroupingUsed(false); //no thousand separator

		format = NumberFormat.getInstance();
		format.setGroupingUsed(false);//no thousand separator

		activeTalent = INIT_TALENT;
	}


	@Override
	protected AbstractFacetSectionFactory createSectionFactory() {
		return new SectionFactoryWeaponCC();
	}

	@Override
	protected FacetWeaponCC createNewFacet() {
		return new FacetWeaponCC();
	}

	@Override
	public Class<FacetWeaponCC> getFacetClass() {
		return FacetWeaponCC.class;
	}
	
	/**
	 *
	 */
	public void handleTalentsSelected() {
		UUID selectedTalentUUID = compositeEditWeaponCC.getSelectedTalentUUID();		
		if(selectedTalentUUID != null){			
			activeTalent = facet.getTalentReferenceForUUID(selectedTalentUUID);
			compositeEditWeaponCC.setGroupWeaponValuesTalentText(activeTalent.getSavedName());
			compositeEditWeaponCC.setStatusButtonTalentDeleteEnabled(true);
			compositeEditWeaponCC.setStatusWeaponValuesEnabled(true);
			updateAllWeaponCombatValues();
		}else{
			activeTalent = INIT_TALENT;
			compositeEditWeaponCC.setStatusButtonTalentDeleteEnabled(false);
			compositeEditWeaponCC.setStatusWeaponValuesEnabled(false);
		}
	}

	/**
	 *
	 */
	public void handleTalentsAdd() {
		// LATER add condition for that talents use (like KK>=15)
		DialogChooseEntity dialog = new DialogChooseEntity(compositeEditWeaponCC.getShell());
		//customize dialog
		dialog.setDialogTitle(DIALOG_TITLE_CHOOSE_TALENT);
		dialog.setSectionTitle(TEXT_SECTION_TALENTS);
		dialog.setActiveBaseFacet(FacetTalent.class);
		dialog.setUUIDForUncategorized(EntityCategorized.CATEGORY_UNCATEGORIZED_UUID_DEFAULT);
		dialog.setNameForUncategorized(EntityCategorized.CATEGORY_UNCATEGORIZED_NAME_DEFAULT);				
		try {					
			Collection<EntityFacetReferences> elements = serviceResolverTalents.resolveAllEntities();	
			logger.debug("Number of Talents resolved: "+elements.size());
			dialog.setEntityStructure(new ArrayList<EntityCategorized>(elements));
		} catch (EntityLoadException e) {
			logger.error(e);					
		}
		//pre set value
		String selectedTalentName = compositeEditWeaponCC.getSelectedTalentName();
		UUID selectedTalentUUID = compositeEditWeaponCC.getSelectedTalentUUID();
		dialog.setValue(new UUIDString(selectedTalentUUID, selectedTalentName));		
		
		if(dialog.open()==DialogChooseEntity.OK){
			UUIDString chosenTalent = dialog.getValue();		
			//
			UUIDReference talentReference = 
					UUIDReference.extractUUIDReference(chosenTalent.uuid,chosenTalent.string, EntityCategorized.class);				
			WeaponCC_CombatValues currentWeaponValues = facet.getWeaponValuesByTalent(activeTalent);
			WeaponCC_CombatValues newValues;
			if(currentWeaponValues != null ){
				// clone weapon values hereby, if any values are active
				try {
					newValues = (WeaponCC_CombatValues)currentWeaponValues.clone();
				} catch (CloneNotSupportedException e) {
					newValues = new WeaponCC_CombatValues();
				}
			}else{
				newValues = new WeaponCC_CombatValues();
			}
			facet.setWeaponValuesByTalent(talentReference, newValues);			
		}		
	}

	/** */
	public void handleTalentsDelete() {		
		UUID  selectedTalentUUID = compositeEditWeaponCC.getSelectedTalentUUID();
		if(selectedTalentUUID != null){
			UUIDReference reference = facet.getTalentReferenceForUUID(selectedTalentUUID);
			facet.removeWeaponValuesByTalent(reference);
			if(reference.equals(activeTalent)){
				activeTalent = INIT_TALENT;
			}
		}		
	}
	
	public void modifyLength(String newLength) {	
		if(facet == null) return;	
		Number valueNumber;
		try {
			if(compositeEditWeaponCC != null){
				compositeEditWeaponCC.setDecorationLengthStatus(false);
			}
			removeStateEvent(STATE_EVENT_Length_ERROR);
			valueNumber =  format.parse(newLength);		
			if (valueNumber instanceof Integer) {
				Integer valueInteger = (Integer) valueNumber;
				facet.setLength(valueInteger.doubleValue());
			}
			if (valueNumber instanceof Double) {
				Double valueDouble = (Double) valueNumber;
				facet.setLength(valueDouble.doubleValue());
			}
		} catch (ParseException e) {
			if(compositeEditWeaponCC != null){
				compositeEditWeaponCC.setDecorationLengthStatus(true);	
			}
			addStateEvent(STATE_EVENT_Length_ERROR);			
		}	
	}
	
	public void modifyBf(String newBf) {	
		if(facet == null) return;	
		Number valueNumber;
		try {
			if(compositeEditWeaponCC != null){
				compositeEditWeaponCC.setDecorationBfStatus(false);
			}
			removeStateEvent(STATE_EVENT_Bf_ERROR);
			valueNumber =  format.parse(newBf);		
			if (valueNumber instanceof Integer) {
				Integer valueInteger = (Integer) valueNumber;
				facet.setBf(valueInteger);
			}
		} catch (ParseException e) {
			if(compositeEditWeaponCC != null){
				compositeEditWeaponCC.setDecorationBfStatus(true);	
			}
			addStateEvent(STATE_EVENT_Bf_ERROR);			
		}	
	}
	
	public void modifyTp(String newTp) {	
		if(facet == null) return;			
		facet.setTp(activeTalent,newTp);		
	}

	public void modifyTpKKBase(String newTpKKBase) {	
		if(facet == null) return;	
		Number valueNumber;
		try {
			if(compositeEditWeaponCC != null){
				compositeEditWeaponCC.setDecorationTpKKBaseStatus(false);
			}
			removeStateEvent(STATE_EVENT_TpKKBase_ERROR);
			valueNumber =  format.parse(newTpKKBase);		
			if (valueNumber instanceof Integer) {
				Integer valueInteger = (Integer) valueNumber;
				facet.setTpKK_Base(activeTalent,valueInteger);
			}
		} catch (ParseException e) {
			if(compositeEditWeaponCC != null){
				compositeEditWeaponCC.setDecorationTpKKBaseStatus(true);	
			}
			addStateEvent(STATE_EVENT_TpKKBase_ERROR);			
		}	
	}
	
	public void modifyTpKKStep(String newTpKKStep) {	
		if(facet == null) return;	
		Number valueNumber;
		try {
			if(compositeEditWeaponCC != null){
				compositeEditWeaponCC.setDecorationTpKKStepStatus(false);
			}
			removeStateEvent(STATE_EVENT_TpKKStep_ERROR);
			valueNumber =  format.parse(newTpKKStep);		
			if (valueNumber instanceof Integer) {
				Integer valueInteger = (Integer) valueNumber;
				facet.setTpKK_Step(activeTalent,valueInteger);
			}
		} catch (ParseException e) {
			if(compositeEditWeaponCC != null){
				compositeEditWeaponCC.setDecorationTpKKStepStatus(true);	
			}
			addStateEvent(STATE_EVENT_TpKKStep_ERROR);			
		}	
	}

	public void modifyIni(String newIni) {	
		if(facet == null) return;	
		Number valueNumber;
		try {
			if(compositeEditWeaponCC != null){
				compositeEditWeaponCC.setDecorationIniStatus(false);
			}
			removeStateEvent(STATE_EVENT_Ini_ERROR);
			valueNumber =  format.parse(newIni);		
			if (valueNumber instanceof Integer) {
				Integer valueInteger = (Integer) valueNumber;
				facet.setIni(activeTalent,valueInteger);
			}
		} catch (ParseException e) {
			if(compositeEditWeaponCC != null){
				compositeEditWeaponCC.setDecorationIniStatus(true);	
			}
			addStateEvent(STATE_EVENT_Ini_ERROR);			
		}	
	}
	
	public void modifyWmAT(String newWmAT) {	
		if(facet == null) return;	
		Number valueNumber;
		try {
			if(compositeEditWeaponCC != null){
				compositeEditWeaponCC.setDecorationWmATStatus(false);
			}
			removeStateEvent(STATE_EVENT_WmAT_ERROR);
			valueNumber =  format.parse(newWmAT);		
			if (valueNumber instanceof Integer) {
				Integer valueInteger = (Integer) valueNumber;
				facet.setWmAT(activeTalent, valueInteger);
			}
		} catch (ParseException e) {
			if(compositeEditWeaponCC != null){
				compositeEditWeaponCC.setDecorationWmATStatus(true);	
			}
			addStateEvent(STATE_EVENT_WmAT_ERROR);			
		}	
	}
	
	public void modifyWmPA(String newWmPA) {	
		if(facet == null) return;	
		Number valueNumber;
		try {
			if(compositeEditWeaponCC != null){
				compositeEditWeaponCC.setDecorationWmPAStatus(false);
			}
			removeStateEvent(STATE_EVENT_WmPA_ERROR);
			valueNumber =  format.parse(newWmPA);		
			if (valueNumber instanceof Integer) {
				Integer valueInteger = (Integer) valueNumber;
				facet.setWmPA(activeTalent,valueInteger);
			}
		} catch (ParseException e) {
			if(compositeEditWeaponCC != null){
				compositeEditWeaponCC.setDecorationWmPAStatus(true);	
			}
			addStateEvent(STATE_EVENT_WmPA_ERROR);			
		}	
	}
	/**
	 *
	 */
	public void modifyDkBits() {
		int dkBits = 0;
		dkBits |= compositeEditWeaponCC.getBtDk_H_Selected()?WeaponCC_CombatValues.DK_H:0;
		dkBits |= compositeEditWeaponCC.getBtDk_N_Selected()?WeaponCC_CombatValues.DK_N:0;
		dkBits |= compositeEditWeaponCC.getBtDk_S_Selected()?WeaponCC_CombatValues.DK_S:0;
		dkBits |= compositeEditWeaponCC.getBtDk_P_Selected()?WeaponCC_CombatValues.DK_P:0;
		if(dkBits != 0){
			facet.setDkBits(activeTalent,dkBits);
			removeStateEvent(STATE_EVENT_DK_BITS_ERROR);
		}else{
			addStateEvent(STATE_EVENT_DK_BITS_ERROR);
		}
	}

	/**
	 *
	 */
	public void modifySpecialBits() {
		int specialBits = 0;
		specialBits |= compositeEditWeaponCC.getBtSpecTwoHandedSelected()?WeaponCC_CombatValues.SPECIAL_TWO_HANDED:0;
		specialBits |= compositeEditWeaponCC.getBtSpecPrivilegedSelected()?WeaponCC_CombatValues.SPECIAL_PRIVILIGED:0;
		specialBits |= compositeEditWeaponCC.getBtSpecImprovisedSelected()?WeaponCC_CombatValues.SPECIAL_IMPROVISED:0;
		//always set, might be no specials present
		facet.setSpecialBits(activeTalent,specialBits);
	}
	
	
	public void updateLength(Double newLength) {
		if(newLength != null && compositeEditWeaponCC != null){
			if( ! newLength.equals(FacetWeaponCC.UNSET_LENGTH)){				
				compositeEditWeaponCC.setLength(format.format(newLength));
				removeStateEvent(STATE_EVENT_Length_WARNING);
			}else{
				compositeEditWeaponCC.setLength("");
				addStateEvent(STATE_EVENT_Length_WARNING);
			}				
		}			
	}
	
	public void updateBf(Integer newBf) {
		if(newBf != null && compositeEditWeaponCC != null){
			if( ! newBf.equals(FacetWeaponCC.UNSET_BF)){				
				compositeEditWeaponCC.setBf(format.format(newBf));
				removeStateEvent(STATE_EVENT_Bf_WARNING);
			}else{
				compositeEditWeaponCC.setBf("");
				addStateEvent(STATE_EVENT_Bf_WARNING);
			}				
		}			
	}
	
	public void updateTP(UUIDReference talent, String newTp){	
			//LATER get string from DiceRollDefinition
		if(compositeEditWeaponCC != null ){
			if(newTp != null && ! newTp.equals(WeaponCC_CombatValues.UNSET_TP)&& activeTalent.equals(talent)){				
				compositeEditWeaponCC.setTp(newTp);
				removeStateEvent(STATE_EVENT_Tp_WARNING);
			}else{
				compositeEditWeaponCC.setTp("");
				addStateEvent(STATE_EVENT_Tp_WARNING);
			}				
		}			
	}
	
	public void updateTpKKBase(UUIDReference talent,Integer newTpKKBase) {
		if( compositeEditWeaponCC != null ){
			if(newTpKKBase != null && ! newTpKKBase.equals(WeaponCC_CombatValues.UNSET_TP_KK_BASE)&& activeTalent.equals(talent)){				
				compositeEditWeaponCC.setTpKKBase(format.format(newTpKKBase));
				removeStateEvent(STATE_EVENT_TpKKBase_WARNING);
			}else{
				compositeEditWeaponCC.setTpKKBase("");
				addStateEvent(STATE_EVENT_TpKKBase_WARNING);
			}				
		}			
	}
		
	public void updateTpKKStep(UUIDReference talent,Integer newTpKKStep) {
		if(compositeEditWeaponCC != null ){
			if(newTpKKStep != null &&  ! newTpKKStep.equals(WeaponCC_CombatValues.UNSET_TP_KK_STEP) && activeTalent.equals(talent)){				
				compositeEditWeaponCC.setTpKKStep(format.format(newTpKKStep));
				removeStateEvent(STATE_EVENT_TpKKStep_WARNING);
			}else{
				compositeEditWeaponCC.setTpKKStep("");
				addStateEvent(STATE_EVENT_TpKKStep_WARNING);
			}				
		}			
	}
			
	public void updateIni(UUIDReference talent,Integer newIni) {
		if(compositeEditWeaponCC != null ){
			if(newIni != null &&  ! newIni.equals(WeaponCC_CombatValues.UNSET_INI)&& activeTalent.equals(talent)){				
				compositeEditWeaponCC.setIni(format.format(newIni));
				removeStateEvent(STATE_EVENT_Ini_WARNING);
			}else{
				compositeEditWeaponCC.setIni("");
				addStateEvent(STATE_EVENT_Ini_WARNING);
			}				
		}			
	}
	
	public void updateWmAT(UUIDReference talent,Integer newWmAT) {
		if(compositeEditWeaponCC != null ){
			if(newWmAT != null &&  ! newWmAT.equals(WeaponCC_CombatValues.UNSET_WM_AT)&& activeTalent.equals(talent)){				
				compositeEditWeaponCC.setWmAT(format.format(newWmAT));
				removeStateEvent(STATE_EVENT_WmAT_WARNING);
			}else{
				compositeEditWeaponCC.setWmAT("");
				addStateEvent(STATE_EVENT_WmAT_WARNING);
			}				
		}			
	}
	
	public void updateWmPA(UUIDReference talent,Integer newWmPA) {
		if(compositeEditWeaponCC != null){
			if(newWmPA != null &&  ! newWmPA.equals(WeaponCC_CombatValues.UNSET_WM_PA) && activeTalent.equals(talent)){				
				compositeEditWeaponCC.setWmPA(format.format(newWmPA));
				removeStateEvent(STATE_EVENT_WmPA_WARNING);
			}else{
				compositeEditWeaponCC.setWmPA("");
				addStateEvent(STATE_EVENT_WmPA_WARNING);
			}				
		}			
	}
			
	public void updateDkBits(UUIDReference talent, Integer newDkBits){
		if(compositeEditWeaponCC != null ){
			if(newDkBits != null && activeTalent.equals(talent)){
				compositeEditWeaponCC.setBtDk_H_Selected(
						(newDkBits & WeaponCC_CombatValues.DK_H) != 0);
				compositeEditWeaponCC.setBtDk_N_Selected(
						(newDkBits & WeaponCC_CombatValues.DK_N) != 0);
				compositeEditWeaponCC.setBtDk_S_Selected(
						(newDkBits & WeaponCC_CombatValues.DK_S) != 0);
				compositeEditWeaponCC.setBtDk_P_Selected(
						(newDkBits & WeaponCC_CombatValues.DK_P) != 0);
			}else{
				compositeEditWeaponCC.setBtDk_H_Selected(false);
				compositeEditWeaponCC.setBtDk_N_Selected(false);
				compositeEditWeaponCC.setBtDk_S_Selected(false);
				compositeEditWeaponCC.setBtDk_P_Selected(false);
			}			
		}
	}

	public void updateSpecialBits(UUIDReference talent, Integer specialBits){
		if(compositeEditWeaponCC != null ){
			if(specialBits != null && activeTalent.equals(talent)){
				compositeEditWeaponCC.setBtSpecTwoHandedSelected(
						(specialBits & WeaponCC_CombatValues.SPECIAL_TWO_HANDED) != 0);
				compositeEditWeaponCC.setBtSpecPrivilegedSelected(
						(specialBits & WeaponCC_CombatValues.SPECIAL_PRIVILIGED) != 0);
				compositeEditWeaponCC.setBtSpecImprovisedSelected(
						(specialBits & WeaponCC_CombatValues.SPECIAL_IMPROVISED) != 0);
			}else{
				compositeEditWeaponCC.setBtSpecTwoHandedSelected(false);
				compositeEditWeaponCC.setBtSpecPrivilegedSelected(false);
				compositeEditWeaponCC.setBtSpecImprovisedSelected(false);
			}			
		}
	}
	
	@Override
	protected void updateAll(FacetWeaponCC facet) {		
		updateLength(facet.getLength());
		updateBf(facet.getBf());		
		updateTalentsInternal(facet.getTalents());
		updateAllWeaponCombatValues();		
	}
	
	@Override
	protected void updateClearUI() {
		updateLength(FacetWeaponCC.UNSET_LENGTH);
		updateBf(FacetWeaponCC.UNSET_BF);
		updateTalentsInternal(FacetWeaponCC.UNSET_TALENTS);
		updateAllWeaponCombatValues();		
	}

	/**
	 * @param map
	 */
	public void updateTalentsValues(Map<?, ?> map) {
		Set<?> keys = map.keySet();
		List<UUIDReference> talentReferences = new ArrayList<UUIDReference>();
		for (Object object : keys) {
			if (object instanceof UUIDReference) {
				UUIDReference talentName = (UUIDReference) object;
				talentReferences.add(talentName);
			}
		}	
		updateTalentsInternal(talentReferences);	
	}	

	protected void updateTalentsInternal(List<UUIDReference> newTalents) {
		if(compositeEditWeaponCC != null){
			if(newTalents != null && ! newTalents.isEmpty()){				
				//at first sort 
				UUIDReference[] talentReferences = newTalents.toArray(new UUIDReference[newTalents.size()]);
				Arrays.sort(talentReferences);
				String[] talentNames = new String[talentReferences.length];
				UUID[] talentUuids	 = new UUID[talentReferences.length];
				//split to other two arrays
				for (int i = 0; i < talentReferences.length; i++) {
					talentNames[i] = talentReferences[i].getSavedName();
					talentUuids[i] = talentReferences[i].getSavedUuid();
				}
				compositeEditWeaponCC.setTalents(talentNames, talentUuids);
				removeStateEvent(STATE_EVENT_Talents_WARNING);
			}else{
				compositeEditWeaponCC.setTalents(new String[0], new UUID[0]);
				addStateEvent(STATE_EVENT_Talents_WARNING);
			}				
		}
	}
	
	/**
	 * @param weaponValuesByTalent
	 */
	protected void updateAllWeaponCombatValues() {
		if(activeTalent != null && facet != null){
			WeaponCC_CombatValues weaponValues = facet.getWeaponValuesByTalent(activeTalent);
			if(weaponValues != null){
				updateTP(activeTalent,			weaponValues.getTp());
				updateTpKKBase(activeTalent,	weaponValues.getTpKK_Base());
				updateTpKKStep(activeTalent,	weaponValues.getTpKK_Step());
				updateIni(activeTalent,			weaponValues.getIni());
				updateWmAT(activeTalent,		weaponValues.getWmAT());
				updateWmPA(activeTalent,		weaponValues.getWmPA());
				updateDkBits(activeTalent,		weaponValues.getDkBits());
				updateSpecialBits(activeTalent,	weaponValues.getSpecialBits());
				return;
			}			
		}
		updateTP(activeTalent,			null);
		updateTpKKBase(activeTalent,	null);
		updateTpKKStep(activeTalent,	null);
		updateIni(activeTalent,			null);
		updateWmAT(activeTalent,		null);
		updateWmPA(activeTalent,		null);
		updateDkBits(activeTalent,		null);
		updateSpecialBits(activeTalent,	null);		
	}

	

	@Override
	protected void preSetSection() {
		super.preSetSection();
		if(section != null){
			Control client = section.getClient();
			if (client instanceof CompositeEditWeaponCC) {
				CompositeEditWeaponCC compositeEditItem = (CompositeEditWeaponCC) client;
				deRegisterUIListeners(compositeEditItem);
			}
		}
	}

	@Override
	protected void postSetSection() {		
		if(section != null){
			Control client = section.getClient();
			if (client instanceof CompositeEditWeaponCC) {
				compositeEditWeaponCC = (CompositeEditWeaponCC) client;
				registerUIListeners(compositeEditWeaponCC);
			}
		}
		super.postSetSection();
	}

	@Override
	protected void preSetNewFacet() {
		super.preSetNewFacet();
		if(facet !=  null){
			deRegisterModelListeners(facet);
		}
	}

	@Override
	protected void postSetNewFacet() {
		super.postSetNewFacet();
		if(facet !=  null){
			registerModelListeners(facet);
		}
	}

	protected void registerUIListeners(CompositeEditWeaponCC compositeEditItem) {
		compositeEditItem.registerUIListener(uilFacetWeaponCC);
	}

	protected void deRegisterUIListeners(CompositeEditWeaponCC compositeEditItem) {
		compositeEditItem.deRegisterUIListener(uilFacetWeaponCC);
	}

	protected void registerModelListeners(FacetWeaponCC facet) {
		facet.getPropertyChangeSupport().addPropertyChangeListener(pclFacetWeaponCC);
	}

	protected void deRegisterModelListeners(FacetWeaponCC facet) {
		facet.getPropertyChangeSupport().removePropertyChangeListener(pclFacetWeaponCC);
	}

	public void setTalentResolver(IServiceResolver_EntityTalent serviceResolverTalents) {
		this.serviceResolverTalents = serviceResolverTalents;		
	}

	protected class UILFacetWeaponCC implements IUiChangeListener{

		@Override
		public void uiChanged(UiChangeEvent event) {
			Integer index = event.getIndex();
			switch (index) {

				case CompositeEditWeaponCC.IDX_TP:{
					String tpString = (String)event.getNewValue();
					modifyTp(tpString);
					break;
				}
				case CompositeEditWeaponCC.IDX_TP_KK_BASE:{
					String tpKKBase = (String)event.getNewValue();
					modifyTpKKBase(tpKKBase);
					break;
				}
				case CompositeEditWeaponCC.IDX_TP_KK_STEP:{
					String tpKKStep = (String)event.getNewValue();
					modifyTpKKStep(tpKKStep);
					break;
				}
				case CompositeEditWeaponCC.IDX_LENGTH:{
					String length = (String)event.getNewValue();
					modifyLength(length);
					break;
				}
				case CompositeEditWeaponCC.IDX_BF:{
					String bf = (String)event.getNewValue();
					modifyBf(bf);
					break;
				}
				case CompositeEditWeaponCC.IDX_INI:{
					String ini = (String)event.getNewValue();
					modifyIni(ini);
					break;
				}
				case CompositeEditWeaponCC.IDX_WM_AT:{
					String wmAT = (String)event.getNewValue();
					modifyWmAT(wmAT);
					break;
				}
				case CompositeEditWeaponCC.IDX_WM_PA:{
					String wmPA = (String)event.getNewValue();
					modifyWmPA(wmPA);
					break;
				}
				case CompositeEditWeaponCC.IDX_DK_H:
				case CompositeEditWeaponCC.IDX_DK_N:
				case CompositeEditWeaponCC.IDX_DK_S:
				case CompositeEditWeaponCC.IDX_DK_P:
				{
					modifyDkBits();
					break;
				}
				case CompositeEditWeaponCC.IDX_SPECIAL_TWO_HANDED:
				case CompositeEditWeaponCC.IDX_SPECIAL_PRIVILEGED:
				case CompositeEditWeaponCC.IDX_SPECIAL_IMPROVISED:
				{
					modifySpecialBits();
					break;
				}
				default:
					logger.info("unknown uiChangeIndex: "+event.getIndex());
					break;
			}
		}

		@Override
		public void commandIssued(int index, Object... parameters) {
			switch (index) {
				case CompositeEditWeaponCC.CMD_TALENTS_SELECTED:{
					handleTalentsSelected();
					break;
				}
				case CompositeEditWeaponCC.CMD_TALENTS_ADD:{
					handleTalentsAdd();
					break;
				}
				case CompositeEditWeaponCC.CMD_TALENTS_REMOVE:{
					handleTalentsDelete();
					break;
				}
				default:
					break;
			}
		}
	}


	protected class PCLFacetWeaponCC implements PropertyChangeListener{
		@Override
		public void propertyChange(PropertyChangeEvent evt) {
			if (evt instanceof IndexedPropertyChangeEvent) {
				IndexedPropertyChangeEvent idxEvt = (IndexedPropertyChangeEvent) evt;
				Integer index = idxEvt.getIndex();
				//events newValues have special appearance [<talent>,<newValue>]
				Object obj = idxEvt.getNewValue();
				if (obj instanceof Object[]) {
					Object[] array = (Object[]) obj;
					UUIDReference talent = (UUIDReference)array[FacetWeaponCC.ARRAY_IDX_TALENT];
					switch (index) {
						case WeaponCC_CombatValues.PI_TP:{
							String newTP = (String)array[FacetWeaponCC.ARRAY_IDX_VALUE];
							updateTP(talent,newTP);
							break;
						}
						case WeaponCC_CombatValues.PI_TP_KK_BASE:{
							Integer newTpKKBase = (Integer)array[FacetWeaponCC.ARRAY_IDX_VALUE];
							updateTpKKBase(talent,newTpKKBase);
							break;
						}
						case WeaponCC_CombatValues.PI_TP_KK_STEP:{
							Integer newTpKKStep = (Integer)array[FacetWeaponCC.ARRAY_IDX_VALUE];
							updateTpKKStep(talent,newTpKKStep);
							break;
						}

						case WeaponCC_CombatValues.PI_INI:{
							Integer newIni = (Integer)array[FacetWeaponCC.ARRAY_IDX_VALUE];
							updateIni(talent,newIni);
							break;
						}
						case WeaponCC_CombatValues.PI_WM_AT:{
							Integer newWmAT = (Integer)array[FacetWeaponCC.ARRAY_IDX_VALUE];
							updateWmAT(talent,newWmAT);
							break;
						}
						case WeaponCC_CombatValues.PI_WM_PA:{
							Integer newWmPA = (Integer)array[FacetWeaponCC.ARRAY_IDX_VALUE];
							updateWmPA(talent,newWmPA);
							break;
						}
						case WeaponCC_CombatValues.PI_DK_BITS:{
							Integer newDkBits = (Integer)array[FacetWeaponCC.ARRAY_IDX_VALUE];
							updateDkBits(talent,newDkBits);
							break;
						}
						case WeaponCC_CombatValues.PI_SPECIAL_BITS:{
							Integer newSpecialBits = (Integer)array[FacetWeaponCC.ARRAY_IDX_VALUE];
							updateSpecialBits(talent,newSpecialBits);
							break;
						}
						default:
							logger.debug("unknown propertyChangeIndex of weapon values: "+index);
							break;
					}
				}else{
					switch (index) {
						case FacetWeaponCC.PI_TALENTS_VALUES:{
							Map<?,?> map = (Map<?,?>)idxEvt.getNewValue();
							updateTalentsValues(map);
							break;
						}
						case FacetWeaponCC.PI_LENGTH:{
							Double newLength = (Double)idxEvt.getNewValue();
							updateLength(newLength);
							break;
						}
						case FacetWeaponCC.PI_BF:{
							Integer newBf = (Integer)idxEvt.getNewValue();
							updateBf(newBf);
							break;
						}
					}
				}
			}
		}
	}

	
}
